<!DOCTYPE HTML>
<html>
<head>
  <title>Test for Bug 989198</title>
  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
  <script type="text/javascript" src="/tests/SimpleTest/NativeKeyCodes.js"></script>
  <script type="text/javascript" src="bug989198_helper.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body onload="runTests();">
<a target="_blank"
   href="https://bugzilla.mozilla.org/show_bug.cgi?id=989198">Mozilla Bug 989198</a>
<p id="display"></p>
<div id="content">
</div>
<pre id="test">
<script type="application/javascript">

SimpleTest.waitForExplicitFinish();
SimpleTest.requestFlakyTimeout("untriaged");

var testsForEventOrder = [
  {
    description: "Testing the order of the events (OOP)",
    expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
                        kParent | kKeyDownEvent,
                        kChild | kKeyDownEvent,
                        kParent | kAfterEvent | kKeyDownEvent ],
                      [ kParent | kBeforeEvent | kKeyUpEvent,
                        kParent | kKeyUpEvent,
                        kChild | kKeyUpEvent,
                        kParent | kAfterEvent | kKeyUpEvent ] ],
    resultEvents: [],
    classifiedEvents: [ [], [] ],
    doPreventDefaultAt: kUnknownEvent
  },
  {
    description: "Testing the order of the events (OOP), calling " +
                 "preventDefault() at \"mozbrowserbeforekeydown\" event",
    expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
                        kParent | kAfterEvent | kKeyDownEvent ],
                      [ kParent | kBeforeEvent | kKeyUpEvent,
                        kParent | kKeyUpEvent,
                        kChild | kKeyUpEvent,
                        kParent | kAfterEvent | kKeyUpEvent ] ],
    resultEvents: [],
    classifiedEvents: [ [], [] ],
    doPreventDefaultAt: kParent | kBeforeEvent | kKeyDownEvent
  },
  {
    description: "Testing the order of the events (OOP), calling " +
                 "preventDefault() at \"mozbrowserbeforekeyup\" event",
    expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
                        kParent | kKeyDownEvent,
                        kChild | kKeyDownEvent,
                        kParent | kAfterEvent | kKeyDownEvent ],
                      [ kParent | kBeforeEvent | kKeyUpEvent,
                        kParent | kAfterEvent | kKeyUpEvent ] ],
    resultEvents: [],
    classifiedEvents: [ [], [] ],
    doPreventDefaultAt: kParent | kBeforeEvent | kKeyUpEvent
  },
  {
    description: "Testing the order of the events (OOP), calling " +
                 "preventDefault() at \"keydown\" event in parent process",
    expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
                        kParent | kKeyDownEvent,
                        kParent | kAfterEvent | kKeyDownEvent ],
                      [ kParent | kBeforeEvent | kKeyUpEvent,
                        kParent | kKeyUpEvent,
                        kChild | kKeyUpEvent,
                        kParent | kAfterEvent | kKeyUpEvent ] ],
    resultEvents: [],
    classifiedEvents: [ [], [] ],
    doPreventDefaultAt: kParent | kKeyDownEvent
  },
  {
    description: "Testing the order of the events (OOP), calling " +
                 "preventDefault() at \"keydown\" event in child process",
    expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
                        kParent | kKeyDownEvent,
                        kChild | kKeyDownEvent,
                        kParent | kAfterEvent | kKeyDownEvent ],
                      [ kParent | kBeforeEvent | kKeyUpEvent,
                        kParent | kKeyUpEvent,
                        kChild | kKeyUpEvent,
                        kParent | kAfterEvent | kKeyUpEvent ] ],
    resultEvents: [],
    classifiedEvents: [ [], [] ],
    doPreventDefaultAt: kChild | kKeyDownEvent
  },
  {
    description: "Testing the order of the events (OOP), calling " +
                 "preventDefault() at \"keyup\" event in parent process",
    expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
                        kParent | kKeyDownEvent,
                        kChild | kKeyDownEvent,
                        kParent | kAfterEvent | kKeyDownEvent ],
                      [ kParent | kBeforeEvent | kKeyUpEvent,
                        kParent | kKeyUpEvent,
                        kParent | kAfterEvent | kKeyUpEvent ] ],
    resultEvents: [],
    classifiedEvents: [ [], [] ],
    doPreventDefaultAt: kParent | kKeyUpEvent
  },
  {
    description: "Testing the order of the events (OOP), calling " +
                 "preventDefault() at \"keyup\" event in child process",
    expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
                        kParent | kKeyDownEvent,
                        kChild | kKeyDownEvent,
                        kParent | kAfterEvent | kKeyDownEvent ],
                      [ kParent | kBeforeEvent | kKeyUpEvent,
                        kParent | kKeyUpEvent,
                        kChild | kKeyUpEvent,
                        kParent | kAfterEvent | kKeyUpEvent ] ],
    resultEvents: [],
    classifiedEvents: [ [], [] ],
    doPreventDefaultAt: kChild | kKeyUpEvent
  }
];

function cleanupTest()
{
  teardownHandlers(window, embedderHandler);
  runTests();
}

function testEventOrder()
{
  if (!testsForEventOrder.length) {
    runTests();
    return;
  }
  gCurrentTest = testsForEventOrder.shift();

  synthesizeKey('a', {}, document.getElementById("embedded").contentWindow);
  // It take some time to propagate events to a remote iframe.

  waitAndVerifyResult(0);
}

function waitAndVerifyResult(aCount) {
  expectedEventLength = gCurrentTest.expectedEvents[0].length +
                        gCurrentTest.expectedEvents[1].length;
  if (gCurrentTest.resultEvents.length >= expectedEventLength || aCount > 10) {
    classifyEvents(gCurrentTest);
    verifyResults(gCurrentTest);
    testEventOrder();
  }
  else {
    setTimeout(() => waitAndVerifyResult(aCount + 1),
               100);
  }
}

var tests = [
  function addPermissions() {
    SpecialPowers.pushPermissions(
      [{ type: "before-after-keyboard-event", allow: true, context: document },
       { type: "browser", allow: true, context: document }],
      runTests);
  },
  function addPreferences() {
    SpecialPowers.pushPrefEnv(
      { "set": [["dom.beforeAfterKeyboardEvent.enabled", true],
                ["dom.mozBrowserFramesEnabled", true],
                ["network.disable.ipc.security", true],
                ["dom.ipc.tabs.disabled", false]] },
      runTests);
  },

  // Tests for out-of-process iframe, i.el. <iframe mozbrowser remote>
  function () {
    prepareTest(true);
  },
  testEventOrder,
  cleanupTest
];

function runTests()
{
  if (!tests.length) {
    SimpleTest.finish();
    return;
  }

  var test = tests.shift();
  test();
}

</script>
</body>
</html>
